package com.cswangdao.service.impl;


import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.RandomUtil;
import com.cswangdao.domain.dto.*;

import com.cswangdao.domain.model.*;
import com.cswangdao.domain.po.Order;
import com.cswangdao.domain.po.OrderGoods;

import com.cswangdao.domain.po.User;
import com.cswangdao.domain.vo.ChannelVo;
import com.cswangdao.domain.vo.OrderDetailVo;
import com.cswangdao.domain.vo.WXOrderDetailVo;
import com.cswangdao.domain.vo.WXOrderListVo;
import com.cswangdao.mapper.*;
import com.cswangdao.result.PageResult;
import com.cswangdao.service.OrderService;

import com.cswangdao.utils.SubjectUtil;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.math.BigDecimal;
import java.nio.charset.StandardCharsets;
import java.util.*;
import java.util.function.Consumer;
import java.util.function.Function;


@Service
@Transactional
public class OrderServiceImpl implements OrderService {

    @Autowired
    private MarketOrderMapper orderMapper;

    @Autowired
    private MarketOrderGoodsMapper orderGoodsMapper;

    @Autowired
    private MarketUserMapper userMapper;

    @Autowired
    private MarketGoodsProductMapper goodsProductMapper;

    @Autowired
    private MarketAddressMapper addressMapper;

    @Autowired
    private MarketCartMapper cartMapper;

    @Autowired
    private MarketCouponMapper couponMapper;

    @Autowired
    private MarketCouponUserMapper couponUserMapper;



    @Autowired
    private MarketSystemMapper systemMapper;


    /**
     * @description: 分页查询订单信息
     * @param: orderListDTO
     * @return: com.cswangdao.result.PageResult<com.cswangdao.domain.po.Order>
     */
    @Override
    public PageResult<Order> pageQueryInfo(OrderListDTO orderListDTO) {
        PageHelper.startPage(orderListDTO.getPage(), orderListDTO.getLimit());
        Page<Order> orders = orderMapper.pageQueryInfo(orderListDTO);
        PageResult<Order> result = PageResult.result(orders);
        return result;
    }

    /**
     * @description: 获取订单详情信息
     * @param: orderId
     * @return: com.cswangdao.domain.vo.OrderDetailVo
     */
    @Override
    public OrderDetailVo getOrderDetailById(int orderId) {
        try {
              Order order = orderMapper.getById(orderId);
            if (Objects.isNull(order)) {
                return null;
            }
            List<OrderGoods> orderGoods = orderGoodsMapper.getOrderGoodsByOrderId(orderId);
            Integer userId = order.getUserId();
            User user = userMapper.getUserById(userId);
            OrderDetailVo orderDetailVo = new OrderDetailVo();
            orderDetailVo.setOrder(order);
            orderDetailVo.setOrderGoods(orderGoods);
            AdminInfoDTO userInfo = new AdminInfoDTO();
            userInfo.setAvatar(user.getAvatar());
            userInfo.setNickName(user.getNickname());

            orderDetailVo.setUser(userInfo);
            return orderDetailVo;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * @description: 根据id删除订单
     * @param: orderId
     * @return: boolean
     */
    @Override
    public boolean deleteById(int orderId) {
        try{
             Order order = orderMapper.getById(orderId);
            Short orderStatus = order.getOrderStatus();
            if (orderStatus == 201 || orderStatus == 202 || orderStatus == 301) {
                return false;
            }
            orderMapper.deleteById(orderId);
            orderGoodsMapper.deleteByOrderId(orderId);
            return true;
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * @description: 修改订单状态
     * @param: shipDTO
     * @return: boolean
     */
    @Override
    public boolean modifyOrderStatus(ShipDTO shipDTO) {
        Order order1 = orderMapper.getById(shipDTO.getOrderId());
        Short orderStatus = order1.getOrderStatus();
        if (orderStatus != 201) {
            return false;
        }
        Order order = BeanUtil.copyProperties(shipDTO, Order.class);
        order.setId(shipDTO.getOrderId());
        order.setUpdateTime(new Date());
        order.setShipTime(new Date());
        order.setOrderStatus((short) 301);
        orderMapper.modifyOrderById(order);
        return true;
    }

    /**
     * @description: 获取快递公司信息列表
     * @param:
     * @return: java.util.List<com.cswangdao.domain.vo.ChannelVo>
     */
    @Override
    public List<ChannelVo> channelList() {
        Properties properties = null;
        try {
            InputStream is = OrderServiceImpl.class.getClassLoader().getResourceAsStream("express_vendors.properties");
            if (Objects.isNull(is)){
                throw new RuntimeException("express_vendors.properties not found");
            }
            InputStreamReader isr = new InputStreamReader(is, StandardCharsets.UTF_8);
            properties = new Properties();
            properties.load(isr);
        } catch (IOException e) {
            e.printStackTrace();
            return null;
        }

        Set<Map.Entry<Object, Object>> entries = properties.entrySet();
        List<ChannelVo> list = new ArrayList<>();

        for (Map.Entry<Object, Object> entry : entries) {
            ChannelVo channelVo = new ChannelVo();
            channelVo.setCode((String) entry.getKey());
            channelVo.setName((String) entry.getValue());
            list.add(channelVo);
        }
        return list;
    }

    /**
     * @description: 修改订单状态至已发货
     * @param: refundDTO
     * @return: boolean
     */
    @Override
    public boolean modifyOrderRefund(RefundDTO refundDTO) {
        try {
            Integer orderId = refundDTO.getOrderId();
            Order order = orderMapper.getById(orderId);
            //查询订单状态是否已付款
            if (order.getOrderStatus() != 202) {
                return false;
            }
            //获取订单对应的商品信息
            List<OrderGoods> orderGoods = orderGoodsMapper.getOrderGoodsByOrderId(orderId);
            List<GoodsNumberDTO> goodsNumberDTOS = orderGoods.stream().map(new Function<OrderGoods, GoodsNumberDTO>() {
                @Override
                public GoodsNumberDTO apply(OrderGoods orderGoods) {
                    GoodsNumberDTO goodsNumberDTO = new GoodsNumberDTO();
                    goodsNumberDTO.setGoodsId(orderGoods.getGoodsId());
                    goodsNumberDTO.setNumber(orderGoods.getNumber());

                    return goodsNumberDTO;
                }
            }).toList();
            //恢复商品数量
            for (GoodsNumberDTO goodsNumberDTO : goodsNumberDTOS) {
                goodsProductMapper.updateNumber(goodsNumberDTO);
            }

            //构造退款条件参数
            Order order1 = Order.builder()
                    .id(refundDTO.getOrderId())
                    .refundAmount(refundDTO.getRefundMoney())
                    .refundType("微信支付")
                    .refundContent("已退款")
                    .updateTime(new Date())
                    .refundTime(new Date())
                    .build();
            orderMapper.modifyOrderById(order1);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    @Override
    public Map<String, Object> submit(WXOrderSubmitDTO wxOrderSubmitDTO) {
        Integer addressId = wxOrderSubmitDTO.getAddressId();
        MarketAddress address = null;
        //获取地址信息
        if (addressId == 0) {
            // TODO 用户id
            //获取用户默认地址
            address = addressMapper.getDefaultAddressByUserId(1, 0);
        } else if (addressId > 0) {
            //获取指定地址
            address = addressMapper.getById(addressId);
        }

        Integer cartId = wxOrderSubmitDTO.getCartId();
        //记录购物车状态已选择列表
        List<MarketCart> checkedGoodsList = new ArrayList<>();
        //获取商品总价，优惠卷抵扣之前的价格
        BigDecimal goodsTotalPrice = BigDecimal.ZERO;
        if (cartId == 0) {
            //购物车去付款 TODO 获取用户ID
            List<MarketCart> cartList = cartMapper.getCartListByUserId(1);
            checkedGoodsList = cartList.stream().filter(MarketCart::getChecked).toList();
            goodsTotalPrice = cartList.stream().filter(MarketCart::getChecked)
                    .map(cart -> cart.getPrice().multiply(BigDecimal.valueOf(cart.getNumber())))
                    .reduce(BigDecimal::add)
                    .orElseGet(() -> BigDecimal.ZERO);

        } else if (cartId > 0) {
            //立即购买
            MarketCart cart = cartMapper.getById(cartId);
            checkedGoodsList.add(cart);
            goodsTotalPrice = cart.getPrice().multiply(BigDecimal.valueOf(cart.getNumber()));
        }

        //获取优惠券信息
        Integer couponId = wxOrderSubmitDTO.getCouponId();
        MarketCoupon coupon = couponMapper.getById(couponId);

        //订单总价，优惠券抵扣之后的价格
        BigDecimal orderTotalPrice;
        if (Objects.nonNull(coupon)) {
            //优惠券存在

             orderTotalPrice = goodsTotalPrice.subtract(coupon.getDiscount());
        } else {
            orderTotalPrice = goodsTotalPrice;
        }

        //免运费的最小金额
        double freightMin = Double.parseDouble(systemMapper.getValueIsStringByName("market_express_freight_min"));

        //运费金额
        double freightValue = Double.parseDouble(systemMapper.getValueIsStringByName("market_express_freight_value"));

        //判断是否免运费
        double freight = goodsTotalPrice.compareTo(BigDecimal.valueOf(freightMin)) >= 0 ? 0 : freightValue;

        //实际支付金额，加上运费
        BigDecimal actualPrice = orderTotalPrice.add(BigDecimal.valueOf(freight));
        //生成订单号
        String orderSnPrefix = DateUtil.format(new Date(), "yyyyMMdd");
        String orderSnSuffix = RandomUtil.randomString("0123456789", 6);
        MarketOrder order = MarketOrder.builder()
                // TODO 用户id
                .userId(1)
                .orderSn(orderSnPrefix + orderSnSuffix)
                .orderStatus((short) 102)
                .aftersaleStatus((short) 0)
                .consignee(address.getName())
                .mobile(address.getTel())
                .address(address.toString())
                .message(wxOrderSubmitDTO.getMessage())
                .goodsPrice(goodsTotalPrice)
                .freightPrice(BigDecimal.valueOf(freight))
                .couponPrice(coupon == null ? BigDecimal.ZERO : coupon.getDiscount())
                .integralPrice(BigDecimal.ZERO)
                .grouponPrice(BigDecimal.ZERO)
                .orderPrice(orderTotalPrice)
                .actualPrice(actualPrice)
                .endTime(DateUtil.offsetHour(new Date(),1))
                .addTime(new Date())
                .updateTime(new Date())
                .build();
        orderMapper.addOrderInfo(order);

        // 修改优惠卷状态
        if(Objects.nonNull(coupon)){
            MarketCouponUser couponUser = MarketCouponUser.builder()
                    .id(wxOrderSubmitDTO.getUserCouponId())
                    .status((short) 1)
                    .orderId(order.getId())
                    .usedTime(new Date())
                    .updateTime(new Date())
                    .build();
            couponUserMapper.updateCouponUserById(couponUser);

        }

        List<Integer> cartIds = checkedGoodsList.stream().map(MarketCart::getId).toList();
        cartMapper.deleteBatch(cartIds);

        //更新商品库存
        List<Integer> productIds = checkedGoodsList.stream().map(MarketCart::getProductId).toList();
        List<MarketGoodsProduct> goodsProductList = goodsProductMapper.getProductByIds(productIds);

       // TODO 优化？？？
        for (MarketCart cart : checkedGoodsList) {
            for (MarketGoodsProduct goodsProduct : goodsProductList) {
                if(cart.getProductId().equals(goodsProduct.getId())){
                   if(cart.getNumber() <= goodsProduct.getNumber()){
                       goodsProduct.setNumber(goodsProduct.getNumber() - cart.getNumber());
                       goodsProduct.setUpdateTime(new Date());
                       break;
                   }else{
                       throw new RuntimeException("商品库存不足");
                   }
                }
            }
        }

        for (MarketGoodsProduct goodsProduct : goodsProductList) {
            goodsProductMapper.update2ById(goodsProduct);
        }


        List<MarketOrderGoods> orderGoodsList = BeanUtil.copyToList(checkedGoodsList, MarketOrderGoods.class);
        for (MarketOrderGoods marketOrderGoods : orderGoodsList) {
            marketOrderGoods.setAddTime(new Date());
            marketOrderGoods.setUpdateTime(new Date());
            marketOrderGoods.setOrderId(order.getId());
        }

        orderGoodsMapper.insertBatch(orderGoodsList);

        Map<String, Object> result = new HashMap<>();
        result.put("grouponLinkId",0);
        result.put("orderId", order.getId());
        return result;

    }

    @Override
    public PageResult<WXOrderListVo> queryOrderByUserIdAndStatus(Map<String, Object> map) {

        return queryOrderList(map);
    }

    @Override
    public Map<String, Object> queryOrderDetail(Integer orderId) {
        Order order = orderMapper.getById(orderId);
        WXOrderDetailVo wxOrderDetailVo = BeanUtil.copyProperties(order, WXOrderDetailVo.class);
        List<String> options = new ArrayList<>();
        if(order.getOrderStatus().equals((short) 101)){
           options.add("pay");
           options.add("cancel");
        }else if(order.getOrderStatus().equals((short) 201)){
           options.add("refund");
        }else if(order.getOrderStatus().equals((short) 301)){
           options.add("confirm");
        } else if (order.getOrderStatus().equals((short) 401)) {
           options.add("comment");
           options.add("rebuy");
           options.add("delete");
           options.add("aftersale");
        }
        wxOrderDetailVo.setHandleOption(setHandleOption(options));
        List<OrderGoods> orderGoods = orderGoodsMapper.getOrderGoodsByOrderId(orderId);
        Map<String, Object> result = new HashMap<>();
        result.put("orderInfo", wxOrderDetailVo);
        result.put("orderGoods", orderGoods);
        return result;
    }

    @Override
    public void deleteOrder(Map<String, Object> map) {
        Integer orderId = (Integer) map.get("orderId");
        orderMapper.deleteById(orderId);
        orderGoodsMapper.deleteByOrderId(orderId);
    }

    @Override
    public void confirmOrder(Map<String, Object> map) {
        Integer orderId = (Integer) map.get("orderId");
        Order order = orderMapper.getById(orderId);
        boolean flag = order.getOrderStatus().equals((short) 301);
        if(!flag){
            throw new RuntimeException("订单状态不正确");
        }
        order.setOrderStatus((short) 401);
        Date now = new Date();
        order.setUpdateTime(now);
        order.setConfirmTime(now);
        orderMapper.modifyOrderById(order);
    }

    @Override
    public void cancelOrder(Map<String, Object> map) {
        Integer orderId = (Integer) map.get("orderId");
        Order order = orderMapper.getById(orderId);
        boolean flag = order.getOrderStatus().equals((short) 101);
        if(!flag){
            throw new RuntimeException("订单状态不正确");
        }
        //修改订单状态 取消订单
        order.setOrderStatus((short) 102);
        order.setUpdateTime(new Date());
        orderMapper.modifyOrderById(order);
        //恢复商品库存
        List<OrderGoods> orderGoods = orderGoodsMapper.getOrderGoodsByOrderId(orderId);
        for (OrderGoods orderGood : orderGoods) {
            Integer productId = orderGood.getProductId();
            Short number = orderGood.getNumber();
            GoodsNumberDTO goodsNumberDTO = new GoodsNumberDTO(productId,number);
            goodsProductMapper.updateNumber(goodsNumberDTO);
        }

    }

    @Override
    public void refundOrder(WXRefundDTO wxRefundDTO) {

        Order order = orderMapper.getById(wxRefundDTO.getOrderId());
        boolean flag = order.getOrderStatus().equals((short) 201);
        if(!flag){
            throw new RuntimeException("订单状态不正确");
        }
        //修改订单状态 退款中
        order.setOrderStatus((short) 202);
        order.setUpdateTime(new Date());
        order.setAftersaleStatus((short) 1);
        order.setRefundAmount(wxRefundDTO.getAmount());
        order.setRefundContent(wxRefundDTO.getReason());
        order.setRefundType(wxRefundDTO.getTypeDesc());
        orderMapper.modifyOrderById(order);
    }

    private PageResult<WXOrderListVo> queryOrderList(Map<String, Object> map){
        Integer userId = SubjectUtil.getUserId();
        map.put("userId",userId);
        int showType = (int) map.get("showType");
        if(showType == 1){
            map.put("orderStatus",101);
        }
        else if(showType == 2){
            map.put("orderStatus",201);
        }
        else if(showType == 3){
            map.put("orderStatus",301);
        }
        else if(showType == 4){
            map.put("orderStatus",401);
        }
        PageHelper.startPage((int) map.get("page"), (int) map.get("limit"));
        Page<WXOrderListVo> page = orderMapper.queryOrderByUserIdAndStatus(map);
        page.getResult().stream().forEach(new Consumer<WXOrderListVo>() {
            @Override
            public void accept(WXOrderListVo wxOrderListVo) {
                    List<String> options = new ArrayList<>();
                    if(showType == 1){
                        wxOrderListVo.setIsGroupin(false);
                        wxOrderListVo.setOrderStatusText("待付款");
                        options.add("pay");
                        options.add("cancel");
                    }else if(showType == 2){
                        wxOrderListVo.setIsGroupin(false);
                        wxOrderListVo.setOrderStatusText("待发货");
                        options.add("refund");
                    }else if(showType == 3){
                        wxOrderListVo.setIsGroupin(false);
                        wxOrderListVo.setOrderStatusText("待收货");
                        options.add("confirm");
                    }else if(showType == 4){
                        wxOrderListVo.setIsGroupin(false);
                        wxOrderListVo.setOrderStatusText("待评价");
                        options.add("comment");
                        options.add("rebuy");
                        options.add("delete");
                        options.add("aftersale");
                    }
                    wxOrderListVo.setHandleOption(setHandleOption(options));
            }
        });

        return PageResult.result(page);
    }

    private Map<String,Boolean> setHandleOption(List<String> options){
        Map<String,Boolean> handleOption = new HashMap<>();
        handleOption.put("aftersale",false);
        handleOption.put("cancel",false);
        handleOption.put("comment",false);
        handleOption.put("confirm",false);
        handleOption.put("delete",false);
        handleOption.put("pay",false);
        handleOption.put("rebuy",false);
        handleOption.put("refund",false);
        for (String option : options) {
            handleOption.put(option,true);
        }
        return handleOption;
    }
}
